"""
高德地图客户端
"""
import requests
import time
from typing import List, Dict, Optional
from django.conf import settings


class AMapClient:
    """高德地图API客户端"""
    
    def __init__(self, api_key: Optional[str] = None):
        """
        初始化客户端
        :param api_key: 高德地图API Key
        """
        self.api_key = api_key or settings.AMAP_CONFIG.get('API_KEY')
        self.base_url = settings.AMAP_CONFIG.get('BASE_URL', 'https://restapi.amap.com/v3')
        self.rate_limit = settings.AMAP_CONFIG.get('RATE_LIMIT', 50)
        self.last_request_time = 0
        self.request_count = 0
        self.request_window_start = time.time()
    
    def _check_rate_limit(self):
        """检查并限制请求频率"""
        current_time = time.time()
        
        # 重置计数器（每分钟）
        if current_time - self.request_window_start >= 60:
            self.request_count = 0
            self.request_window_start = current_time
        
        # 检查是否超过限制
        if self.request_count >= self.rate_limit:
            sleep_time = 60 - (current_time - self.request_window_start)
            if sleep_time > 0:
                time.sleep(sleep_time)
                self.request_count = 0
                self.request_window_start = time.time()
        
        self.request_count += 1
    
    def get_distance_matrix(self, origins: List[str], destinations: List[str], 
                           strategy: int = 0) -> Dict:
        """
        获取距离矩阵
        :param origins: 起点坐标列表，格式：["经度,纬度", ...]
        :param destinations: 终点坐标列表，格式：["经度,纬度", ...]
        :param strategy: 路径规划策略（0：速度优先，1：费用优先，2：距离优先，3：不走高速）
        :return: 距离矩阵数据
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/distance"
        params = {
            'key': self.api_key,
            'origins': '|'.join(origins),
            'destinations': '|'.join(destinations),
            'type': strategy,
            'output': 'JSON'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def search_attractions(self, location: str, keywords: str = '', 
                          radius: int = 5000) -> Dict:
        """
        搜索景点
        :param location: 中心点坐标，格式："经度,纬度"
        :param keywords: 关键词
        :param radius: 搜索半径（米）
        :return: 景点搜索结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/place/around"
        params = {
            'key': self.api_key,
            'location': location,
            'keywords': keywords,
            'types': '风景名胜|公园广场',
            'radius': radius,
            'output': 'JSON'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def get_route_planning(self, origin: str, destination: str, 
                          waypoints: Optional[List[str]] = None,
                          strategy: int = 0) -> Dict:
        """
        路径规划（驾车）
        :param origin: 起点坐标，格式："经度,纬度"
        :param destination: 终点坐标，格式："经度,纬度"
        :param waypoints: 途经点列表
        :param strategy: 路径规划策略
        :return: 路径规划结果
        """
        return self.get_driving_route(origin, destination, waypoints, strategy)
    
    def get_driving_route(self, origin: str, destination: str,
                          waypoints: Optional[List[str]] = None,
                          strategy: int = 0) -> Dict:
        """
        驾车路径规划
        :param origin: 起点坐标，格式："经度,纬度"
        :param destination: 终点坐标，格式："经度,纬度"
        :param waypoints: 途经点列表
        :param strategy: 路径规划策略（0：速度优先，1：费用优先，2：距离优先，3：不走高速）
        :return: 路径规划结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/direction/driving"
        params = {
            'key': self.api_key,
            'origin': origin,
            'destination': destination,
            'strategy': strategy,
            'output': 'JSON'
        }
        
        if waypoints:
            params['waypoints'] = '|'.join(waypoints)
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def get_transit_route(self, origin: str, destination: str,
                          city: str = '南昌市', nightflag: int = 0) -> Dict:
        """
        公交路径规划
        :param origin: 起点坐标，格式："经度,纬度"
        :param destination: 终点坐标，格式："经度,纬度"
        :param city: 城市名称，默认'南昌市'
        :param nightflag: 是否计算夜班车，0：不计算，1：计算
        :return: 路径规划结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/direction/transit/integrated"
        params = {
            'key': self.api_key,
            'origin': origin,
            'destination': destination,
            'city': city,
            'nightflag': nightflag,
            'output': 'JSON'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def get_walking_route(self, origin: str, destination: str) -> Dict:
        """
        步行路径规划
        :param origin: 起点坐标，格式："经度,纬度"
        :param destination: 终点坐标，格式："经度,纬度"
        :return: 路径规划结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/direction/walking"
        params = {
            'key': self.api_key,
            'origin': origin,
            'destination': destination,
            'output': 'JSON'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def get_bicycling_route(self, origin: str, destination: str) -> Dict:
        """
        骑行路径规划
        :param origin: 起点坐标，格式："经度,纬度"
        :param destination: 终点坐标，格式："经度,纬度"
        :return: 路径规划结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/direction/bicycling"
        params = {
            'key': self.api_key,
            'origin': origin,
            'destination': destination,
            'output': 'JSON'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def get_route_by_mode(self, origin: str, destination: str,
                          transport_mode: str = 'driving',
                          **kwargs) -> Dict:
        """
        根据交通方式获取路径规划
        :param origin: 起点坐标，格式："经度,纬度"
        :param destination: 终点坐标，格式："经度,纬度"
        :param transport_mode: 交通方式（driving, transit, walking, bicycling）
        :param kwargs: 其他参数（如strategy, city等）
        :return: 路径规划结果
        """
        if transport_mode == 'driving':
            return self.get_driving_route(origin, destination, 
                                         kwargs.get('waypoints'),
                                         kwargs.get('strategy', 0))
        elif transport_mode == 'transit':
            return self.get_transit_route(origin, destination,
                                         kwargs.get('city', '南昌市'),
                                         kwargs.get('nightflag', 0))
        elif transport_mode == 'walking':
            return self.get_walking_route(origin, destination)
        elif transport_mode == 'bicycling':
            return self.get_bicycling_route(origin, destination)
        else:
            raise ValueError(f"不支持的交通方式: {transport_mode}")
    
    def geocode(self, address: str) -> Dict:
        """
        地理编码（地址转坐标）
        :param address: 地址
        :return: 坐标信息
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/geocode/geo"
        params = {
            'key': self.api_key,
            'address': address,
            'output': 'JSON'
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def get_poi_detail(self, poi_id: str) -> Dict:
        """
        获取POI详情（包含图片）
        :param poi_id: POI ID
        :return: POI详情数据
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/place/detail"
        params = {
            'key': self.api_key,
            'id': poi_id,
            'output': 'JSON',
            'extensions': 'all'  # 获取详细信息，包括图片
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def search_pois_by_keyword(self, keyword: str, city: str = '南昌市', 
                               types: str = '风景名胜|公园广场', 
                               page: int = 1, page_size: int = 20) -> Dict:
        """
        根据关键词搜索POI
        :param keyword: 搜索关键词
        :param city: 城市名称，默认'南昌市'
        :param types: POI类型，默认'风景名胜|公园广场'
        :param page: 页码，默认1
        :param page_size: 每页数量，默认20
        :return: 搜索结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/place/text"
        params = {
            'key': self.api_key,
            'keywords': keyword,
            'city': city,
            'types': types,
            'page': page,
            'offset': page_size,
            'output': 'JSON',
            'extensions': 'all'  # 获取详细信息
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")
    
    def search_pois_by_location(self, location: str, keywords: str = '', 
                                 types: str = '风景名胜|公园广场',
                                 radius: int = 5000, page: int = 1, 
                                 page_size: int = 20) -> Dict:
        """
        根据位置搜索POI（周边搜索）
        :param location: 中心点坐标，格式："经度,纬度"
        :param keywords: 关键词
        :param types: POI类型
        :param radius: 搜索半径（米）
        :param page: 页码
        :param page_size: 每页数量
        :return: 搜索结果
        """
        self._check_rate_limit()
        
        url = f"{self.base_url}/place/around"
        params = {
            'key': self.api_key,
            'location': location,
            'keywords': keywords,
            'types': types,
            'radius': radius,
            'page': page,
            'offset': page_size,
            'output': 'JSON',
            'extensions': 'all'  # 获取详细信息
        }
        
        try:
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            data = response.json()
            
            if data.get('status') == '1':
                return data
            else:
                raise Exception(f"高德地图API错误: {data.get('info', '未知错误')}")
        except requests.RequestException as e:
            raise Exception(f"请求高德地图API失败: {str(e)}")

